package com.sis.tool.service;

import com.sis.tool.exception.FileHandleException;
import com.sis.tool.exception.RequestException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.ofdrw.converter.export.ImageExporter;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Service
public class FileConverterService implements IFileConverterService {


    /**
     * 将pdf转换为image
     *
     * @param pdfInputStream
     * @param sourceFileType
     * @param targetFileType
     * @return
     */
    @Override
    public byte[] convertPdfToImage(InputStream pdfInputStream, String sourceFileType, String targetFileType) {
        try {
            // 参数验证
            if (!"pdf".equalsIgnoreCase(sourceFileType)) {
                throw new RequestException("Invalid source type");
            }
            if (!isSupportedImageFormat(targetFileType)) {
                throw new RequestException("Unsupported target format");
            }

            // 创建临时目录
            File tempDir = createTempDirectory();

            // PDF转图片
            List<File> imageFiles = convertPdfToImages(pdfInputStream, targetFileType, tempDir);

            // 打包为ZIP
            ByteArrayOutputStream zipStream = new ByteArrayOutputStream();
            try (ZipOutputStream zos = new ZipOutputStream(zipStream)) {
                for (File imageFile : imageFiles) {
                    ZipEntry entry = new ZipEntry(imageFile.getName());
                    zos.putNextEntry(entry);
                    Files.copy(imageFile.toPath(), zos);
                    zos.closeEntry();
                }
            }

            // 清理临时文件
            deleteTempFiles(tempDir);
            return zipStream.toByteArray();
        } catch (Exception e) {
            throw new FileHandleException("文件格式转换失败: " + e.getMessage());
        }
    }

    /**
     * 将ofd转换为image
     *
     * @param ofdInputStream
     * @param sourceFileType
     * @param targetFileType
     * @return
     */
    @Override
    public byte[] convertOfdToImage(InputStream ofdInputStream, String sourceFileType, String targetFileType) throws IOException {
        // 创建临时目录
        File tempDir = createTempDirectory();

        ImageExporter imageExporter = new ImageExporter(ofdInputStream, tempDir.toPath(), targetFileType, 12d);
        imageExporter.export();

        // 读取转换后的图片文件
        File[] imageFiles = tempDir.listFiles((dir, name) -> name.endsWith(targetFileType));
        if (imageFiles == null || imageFiles.length == 0) {
            throw new FileHandleException("ofd转图片失败");
        }
        // 打包为ZIP
        ByteArrayOutputStream zipStream = new ByteArrayOutputStream();
        try (ZipOutputStream zos = new ZipOutputStream(zipStream)) {
            for (File imageFile : imageFiles) {
                ZipEntry entry = new ZipEntry(imageFile.getName());
                zos.putNextEntry(entry);
                Files.copy(imageFile.toPath(), zos);
                zos.closeEntry();
            }
        }

        // 清理临时文件
        deleteTempFiles(tempDir);

        return zipStream.toByteArray();
    }

    @Override
    public byte[] convertTifToImage(InputStream tifInputStream, String sourceFileType, String targetFileType) throws IOException {
        File tempDir = createTempDirectory();

        try (ImageInputStream iis = ImageIO.createImageInputStream(tifInputStream)) {
            // 1. 获取 TIFF 格式的 ImageReader
            ImageReader reader = ImageIO.getImageReadersByFormatName("TIFF").next();
            reader.setInput(iis);

            // 2. 遍历所有页面
            int pageCount = reader.getNumImages(true);
            for (int i = 0; i < pageCount; i++) {
                BufferedImage image = reader.read(i); // 读取第 i 页
                ImageIO.write(image, targetFileType, new File(tempDir, String.format("page_%03d." + targetFileType, i+1)));
            }
        }

        // 读取转换后的图片文件
        File[] imageFiles = tempDir.listFiles((dir, name) -> name.endsWith(targetFileType));
        if (imageFiles == null || imageFiles.length == 0) {
            throw new FileHandleException("tif转图片失败");
        }
        // 打包为ZIP
        ByteArrayOutputStream zipStream = new ByteArrayOutputStream();
        try (ZipOutputStream zos = new ZipOutputStream(zipStream)) {
            for (File imageFile : imageFiles) {
                ZipEntry entry = new ZipEntry(imageFile.getName());
                zos.putNextEntry(entry);
                Files.copy(imageFile.toPath(), zos);
                zos.closeEntry();
            }
        }

        // 清理临时文件
        deleteTempFiles(tempDir);

        return zipStream.toByteArray();
    }

    private List<File> convertPdfToImages(InputStream pdfStream, String targetType, File outputDir) throws
            IOException {
        List<File> imageFiles = new ArrayList<>();
        PDDocument document = PDDocument.load(pdfStream);

        PDFRenderer pdfRenderer = new PDFRenderer(document);
        for (int page = 0; page < document.getNumberOfPages(); ++page) {
            BufferedImage image = pdfRenderer.renderImageWithDPI(page, 300); // 300 DPI
            File outputFile = new File(outputDir, "page_" + (page + 1) + "." + targetType.toLowerCase());
            ImageIO.write(image, targetType, outputFile);
            imageFiles.add(outputFile);
        }
        document.close();
        return imageFiles;
    }

    private boolean isSupportedImageFormat(String format) {
        String[] supported = {"png", "jpg", "jpeg", "bmp", "tif", "tiff"};
        return Arrays.asList(supported).contains(format.toLowerCase());
    }

    private File createTempDirectory() throws IOException {
        return Files.createTempDirectory("pdf_images_").toFile();
    }

    private void deleteTempFiles(File tempDir) {
        for (File file : tempDir.listFiles()) {
            file.delete();
        }
        tempDir.delete();
    }
}